


#ifndef _PC_DRAW_FUNCTION_H_
#define _PC_DRAW_FUNCTION_H_







#include"gl_TextFont.h"
#include"stl_.h"  




/// <summary>
/// 长方形的结构体。定义上下左右的位置，及长宽。
/// </summary>
typedef struct __rect________
{
    int left;
    int top;
    int right;
    int bottom;
    int width;
    int height;
}rect;

void rect_get_left_top(rect* r);
/// <summary>
/// 根据左上、宽高更新右下的位置。
/// </summary>
void rect_get_right_bottom(rect* r);
/// <summary>
/// 根据右下、左上的位置更新宽高。
/// </summary>
void rect_get_width_height(rect* r);

/// <summary>
/// 绘制函数的结构体，这里只绘制函数和坐标轴刻度，无标题。
/// </summary>
typedef struct __TwoFunction__
{
    int left;
    int top;
    int right;
    int bottom;
    int width;
    int height;   //绘图区域

    TextFont scalefont;                                       //刻度文本的格式
    rect xscale_area, y1scale_area, y2scale_area, curveArea;   //xy的刻度区。
    int scale_curve_gap; //  = 3;                                   //刻度文本与绘图区有一个3像素宽的间隔。避免重合。

    int xscaleFont;// = 0; //x轴刻度显示的格式。= 0显示为数字；= 1作为时间戳，显示的时候以时间的形式显示。  // 这里只有一个选择：数字形式
    int yscaleFont;// = 0; //y轴刻度显示方式。=0左右两边分别显示y1,y2的刻度；=1左边显示刻度；=-1右边显示刻度。
    int scale_gap; // 刻度之间的间隔

    //下面是绘制函数相关的变量与函数。
    COLOR_RGB background;// = RGB_white; //背景颜色。
    COLOR_RGB grid_line_color;// = RGB_lightgray; //网格线的颜色
    COLOR_RGB xy_line_color;// = RGB_black;  //xy轴线的颜色


    float* x1; //函数的x。x坐标的值必须是从小到大的，不然函数绘制会乱
    float* x2; //函数的x。x坐标的值必须是从小到大的，不然函数绘制会乱
    float* y1; //函数的y。
    float* y2; //函数的y2。  这里四个数组不分配内存，直接引用外部的数组。

    //Point2D* points1;  //绘图矩形区域上的点，这里的点是图形坐标。
    //Point2D* points2;  //绘图矩形区域上的点，这里的点是图形坐标。
    float x_min, x_max, y1_min, y1_max, y2_min, y2_max;        //绘图矩形边框上的xy函数值。即xy的最大最小值。
    float x_min_, x_max_, y1_min_, y1_max_, y2_min_, y2_max_;  //xy数组的最大最小值，这个会随着函数点的变化而变化，或者用户自己设定。 
    int pointsNumber1;
    int pointsNumber2;    // xy坐标点的数量。

    COLOR_RGB point_color_1;// = RGB_green; //点颜色。
    COLOR_RGB point_color_2;// = RGB_green; //点颜色。
    int pointsize_1;// = 9;      // 点的尺寸(点的长宽像素点)。根据数组长度自适应大小，在draw_points函数实现。像素增加500，点的尺寸减小1
    int pointsize_2;// = 9;      // 点的尺寸(点的长宽像素点)。
    int pointstyle_1;// = 0;     // 点的形状。0 / 1 （实心 / 空心）圆形；2 / 3（实心 / 空心）正方形；4 / 5（实心 / 空心）三角形；
    int pointstyle_2;// = 1;     // 点的形状。0 / 1 （实心 / 空心）圆形；2 / 3（实心 / 空心）正方形；4 / 5（实心 / 空心）三角形；

    COLOR_RGB line_color_1;// = RGB_blue;  //线条颜色。
    COLOR_RGB line_color_2;// = RGB_blue;  //线条颜色。


    //刻度相关变量
    float delta_x, delta_y1, delta_y2;          //xy轴相邻刻度的差值。这个差值只能是0.2,0.5,1,2,5,10,20,50……
    int xscale_number, yscale_number;           //xy刻度的数量，也是下面5个数组的长度


}TwoFunction;




/// <summary>
/// 初始化绘图类。
/// </summary>
/// <param name="g">绘图函数</param>
/// <param name="function_area">绘制函数的区域。x，y轴的刻度区域，</param>
/// <param name="font">刻度的文本样式</param>
/// <param name="xfont">x轴刻度显示样式。0：显示实际数字；1：作为时间戳显示</param>
/// <param name="yfont">y轴刻度显示样式。=0左右两边分别显示y1,y2的刻度；=1左边显示刻度；=-1右边显示刻度。</param>
void TwoFunction_init(TwoFunction* tw, rect function_area, TextFont* font, int xfont, int yfont);



/// <summary>
/// 绘制points数组的点。
/// </summary>
/// <param name="is_show_y1">是否显示函数y1的点</param>
/// <param name="is_show_y2">是否显示函数y2的点</param>
/// <param name="point_color1">函数y1的点颜色数组。如果有定义颜色数组，则用数组颜色，点的样式是空心圆。否则用默认颜色和样式</param>
/// <param name="point_color2">函数y2的点颜色数组。如果有定义颜色数组，则用数组颜色，点的样式是空心圆。否则用默认颜色和样式</param>
void TwoFunction_draw_points(TwoFunction* tw, bool is_show_y1, bool is_show_y2, COLOR_RGB* point_color1, COLOR_RGB* point_color2);


/// <summary>
/// 绘制两条函数
/// </summary>
/// <param name="is_show_y1">是否显示函数 y1</param>
/// <param name="is_show_y2">是否显示函数 y2</param>
void TwoFunction_draw_func(TwoFunction* tw, bool is_show_y1, bool is_show_y2);




/*
    注意函数的使用顺序。
    drawFunction draw(graphic, functionAera, &scalefont);
    draw.init_func(x, y, n);  //必须第一个调用。初始化xy坐标点的函数值。
    draw.init_yscale();       //必须第二个调用。先根据y的函数值确定y轴刻度占据的宽度，才能计算x轴显示区域的宽度。
    draw.init_xscale(); //初始化了y的刻度文本，才能完全确定x刻度，完成曲线区的划分。这时才能调用get_funcx_in_pic函数。

    draw.draw_scale();    //绘制刻度
    draw.draw_points();    //选择绘制点的格式
    draw.draw_func();     //绘制函数。draw_points只画点，不连线。
*/


/// <summary>
/// 绘制刻度。绘制前需要初始化xy的刻度。 
/// </summary>
/// <param name="is_drawMainGridLine">是否绘制网格线。1：绘制；0：不绘制</param>
void TwoFunction_draw_scale(TwoFunction* tw, int is_drawMainGridLine);


/// <summary>
/// 快速绘制函数版本：直接用单像素点，更新数组的某个点时，直接消隐函数点，如果点在网格线上，用网格线颜色，否则是背景色。
/// 要求：函数点之间没有重合，否则会出错。同时，这个函数不会更新现有坐标系的最大最小值，绘制函数只能是不连线的形式。
/// 绘制函数连线是下一层结构体TwoFunctionPicture调用的。
/// 而且，要已经绘制了整个函数，才能调用快速绘制函数。
/// </summary>
/// <param name="tw">函数结构体</param>
/// <param name="index">更换的点的索引</param>
/// <param name="nx">新点x轴函数值</param>
/// <param name="ny">新点y轴函数值</param>
/// <param name="is_y1">是否y1的函数，如果不是，就是y2的函数</param>
void TwoFunction_replace_point(TwoFunction* tw, int index, float nx, float ny, bool is_y1);



/// <summary>
/// 绘制函数的结构体，这里只绘制函数和坐标轴刻度，无标题。
/// </summary>
typedef struct _____TwoFunctionPicture___
{
    //绘制图表。图表有页边距，标题，X、Y轴标题与X、Y轴刻度。
    //图表格式：用户可自行设置的参数：
    //1、图片的宽，高。
    //2、标题，X、Y轴标题。
    //3、是否显示网格线。
    //4、函数数组


    int titleFontSize;// = size48;             //标题字体大小。
    int xytitleFontSize;// = size24;           //xy轴标题字体大小。
    int scaleFontSize;// = size24;             //刻度字体大小

    COLOR_RGB titleFontColor;// = RGB_black;         //标题字体大小。
    COLOR_RGB xytitleFontColor;// = RGB_black;       //xy轴标题字体大小。
    COLOR_RGB scaleFontColor;// = RGB_black;         //刻度字体大小
    COLOR_RGB legendFontColor;// = RGB_black;        //刻度字体大小

    //下面的变量由函数输入确定或者自动生成。
    int left; // 函数图片位置的左侧坐标。向右增长。
    int top;  // 函数图片位置顶部坐标。向下增长。
    int picWidth;  //图片宽度
    int picHeight; //图片高度

    int marginWidth;// = 20;    //横向的页边距。
    int marginHeight;// = 20;   //纵向的页边距。margin： [ˈmɑːdʒɪn]  n.边缘;页边空白;白边;

    char title[32];// = "Chart Title";             //标题
    char xtitle[32];// = "x title";                //x轴标题
    char y1title[32];// = "y1 title";              //y1标题
    char y2title[32];// = "y2 title";              //y2标题

    int title_Length;// = 0;                       //标题长度。title_Length/2*FontSize就是标题文本的像素长度。
    int xtitle_Length;// = 0;                      //x轴标题长度
    int y1title_Length;// = 0;                     //y1标题长度
    int y2title_Length;// = 0;                     //y2标题长度

    //这里字体的高度像素数是fontSize。数字、字母宽度是高度的一半。

    //下面定义各个分区。init_xxxxAera()会自动根据标题，图例的字体大小，标题长度进行区域划分。
    rect titleAera;  //标题区
    rect xtitleAera; //x轴标题区
    rect y1titleAera; //y轴标题区
    rect y2titleAera; //y轴标题区
    rect functionAera; //函数区

    TextFont titlefont;
    TextFont scalefont;
    TextFont xytitlefont;

    TwoFunction draw;

}TwoFunctionPicture;




/// <summary>
/// 初始化函数图片结构体
/// </summary>
/// <param name="tfw">函数图片结构体</param>
/// <param name="left">函数图片左侧x坐标</param>
/// <param name="top">函数图片顶部y坐标</param>
/// <param name="width">函数图片的宽度</param>
/// <param name="height">函数图片的高度</param>
void TwoFunctionPicture_init(TwoFunctionPicture* tfw, int left, int top, int width, int height);


//先初始化标题，xy轴标题的格式与文本，才能划分区域。

/// <summary>
/// 先初始化文本格式、清空图片，然后初始化主标题，xy轴标题，根据标题大小划分区域，绘制坐标轴与标题。
/// </summary>
/// <param name="title_">图表标题</param>
/// <param name="xtitle_">x轴标题</param>
/// <param name="y1title_">y1的标题</param>
/// <param name="y2title_">y2标题</param>
void TwoFunctionPicture_draw_title(TwoFunctionPicture* tfw, const char* title_, const  char* xtitle_, const  char* y1title_, const char* y2title_);

/// <summary>
/// 绘制函数
/// </summary>
/// <param name="x1">函数1的x坐标</param>
/// <param name="y1">函数1的y坐标</param>
/// <param name="n1">函数1的点个数</param>
/// <param name="x2">函数2的x坐标</param>
/// <param name="y2">函数2的y坐标</param>
/// <param name="n2">函数2的点个数</param>
/// <param name="isline">是否用线连接函数点。如果x坐标数组是从小到大排序好的，才可以用线连接</param>
/// <param name="yfont">x轴刻度显示的格式：= 0左右两边分别显示y1,y2的刻度；= 1左边显示刻度；= -1右边显示刻度。</param>
/// <param name="xfont">x轴刻度显示的格式：= 0显示为数字；= 1作为时间戳，显示的时候以时间的形式显示。</param>
/// <param name="pointcolor1">函数y1的点颜色数组。如果有定义颜色数组，则用数组颜色，点的样式是空心圆。否则用默认颜色和样式</param>
/// <param name="pointcolor2">函数y2的点颜色数组。如果有定义颜色数组，则用数组颜色，点的样式是空心圆。否则用默认颜色和样式</param>
void TwoFunctionPicture_draw_func(TwoFunctionPicture* tfw, float* x1, float* y1, int n1, float* x2, float* y2, int n2,
    bool isline, int yfont, int xfont, COLOR_RGB* pointcolor1, COLOR_RGB* pointcolor2);



/// <summary>
/// 快速绘制函数
/// 快速绘制函数版本：直接用单像素点，更新数组的某个点时，直接消隐函数点，如果点在网格线上，用网格线颜色，否则是背景色。
/// 结合 TwoFunction_replace_point 使用。
/// </summary>
/// <param name="x1">函数1的x坐标</param>
/// <param name="y1">函数1的y坐标</param>
/// <param name="n1">函数1的点个数</param>
/// <param name="x2">函数2的x坐标</param>
/// <param name="y2">函数2的y坐标</param>
/// <param name="n2">函数2的点个数</param>
/// <param name="yfont">x轴刻度显示的格式：= 0左右两边分别显示y1,y2的刻度；= 1左边显示刻度；= -1右边显示刻度。</param>
/// <param name="xfont">x轴刻度显示的格式：= 0显示为数字；= 1作为时间戳，显示的时候以时间的形式显示，这里没有实现这个功能，=1就先不显示x刻度。</param>
/// <param name="is_set_min_max"> 是否设置坐标的极值 ==0，不设置，否则用下面的参数设置 </param>
/// <param name="xmin">x坐标值的最小值</param>
/// <param name="xmax">x坐标值的最大值</param>
/// <param name="y1min">y1坐标值的最小值</param>
/// <param name="y1max">y1坐标值的最大值</param>
/// <param name="y2min">y2坐标值的最小值</param>
/// <param name="y2max">y2坐标值的最大值</param>
void TwoFunctionPicture_fast_draw_func(TwoFunctionPicture* tfw,
    float* x1, float* y1, int n1,
    float* x2, float* y2, int n2,
    int yfont, int xfont, int is_set_min_max,
    float xmin, float xmax,
    float y1min, float y1max,
    float y2min, float y2max);



//调用draw_title会刷新整个图片。因为分区变化了。

//调用draw_func只刷新函数区。


int test_TwoFunctionPicture(void);
//

int test_TwoFunctionPicture_fast(void);




#endif

